package ar.uba.fi.algo3.tp1.modelo.funciones;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;

import ar.uba.fi.algo3.tp1.modelo.excepciones.FuncionInexistente;
import ar.uba.fi.algo3.tp1.vista.ObservadorLista;

public class ListaFunciones implements Iterable<Funcion>, Serializable{

	private ArrayList<Funcion> listaInterna;
	private ArrayList<ObservadorLista> observadores;
	
	public ListaFunciones (){
		this.listaInterna = new ArrayList<Funcion>();
		this.observadores = new ArrayList<ObservadorLista>();
	}
	
	public int size(){
		return listaInterna.size();
	}

	public ArrayList<Funcion> getLista() {
		return listaInterna;
	}

	public ArrayList<ObservadorLista> getObservadores() {
		return observadores;
	}
	
	public void agregarFuncion(Funcion funcion){
		if (!this.funcionYaGuardada(funcion.toString())){
			this.getLista().add(funcion);
			this.notificarObservadores();
		}
	}
	
	public Funcion obtenerFuncion(int posicion){
		return this.getLista().get(posicion);
	}
	
	public Funcion obtenerFuncion(String funcion) throws FuncionInexistente{
		boolean encontrado = false;
		IteradorFunciones iterador = this.iterator();
		Funcion comparada = null;
		while (!encontrado && iterador.hasNext()){
			comparada = iterador.next();
			encontrado = comparada.toString().equals(funcion);
		}
		if (!encontrado) throw new FuncionInexistente();
		return comparada;
	}
	
	public boolean funcionYaGuardada(String funcion){
		boolean encontrado = false;
		IteradorFunciones iterador = this.iterator();
		Funcion comparada = null;
		while (!encontrado && iterador.hasNext()){
			comparada = iterador.next();
			encontrado = comparada.toString().equals(funcion);
		}
		return encontrado;
	}
	
	public void removerFuncion(Funcion funcion){
		this.getLista().remove(funcion);
		this.notificarObservadores();
	}
	
	public void agregarObservadorLista(ObservadorLista observador){
		this.getObservadores().add(observador);
		this.notificarObservadores();
	}
	
	public void notificarObservadores(){
		for (ObservadorLista observador : this.getObservadores()){
			observador.actualizarListado(this);
		}
	}
	
	public IteradorFunciones iterator(){
		return new IteradorFunciones(this);
	}
	
	public boolean isEmpty(){
		return this.listaInterna.isEmpty();
	}
	
	//Clase iterador para la lista de funciones
	public class IteradorFunciones implements Iterator<Funcion>{
		
		private Iterator<Funcion> iteradorInterno;  
		
		public IteradorFunciones(ListaFunciones listaFun){
			this.iteradorInterno = listaFun.getLista().iterator();
		}

		public boolean hasNext() {
			return iteradorInterno.hasNext();
		}

		public Funcion next() {
			return (Funcion)iteradorInterno.next();
		}

		public void remove() {}
	}
}
